/**
 *
 * @author zzhijie
 * @date 2021-02-07
 */
import FSearch from './module/search';
import FTable from './module/table';
import FDialog from './module/dialog';
import FPage from './module/page';
import FBtn from './module/btn';
import FColumnToggle from './module/column-toggle';
import './style.css';
import {deepCopy} from 'js-utils';

export default {
  name: 'f-crud',
  props: {
    config: {
      type: Object,
      default: () => ({})
    },
    data: {
      type: Array,
      default: () => ([])
    },
    page: {
      type: Object,
      default: () => ({})
    },
    tableLoading: {
      type: Boolean,
      default: false
    }
  },
  components: {
    FSearch,
    FTable,
    FDialog,
    FPage,
    FBtn,
    FColumnToggle
  },
  computed: {
    params() {
      let fSearch = this.$fSearch;
      return fSearch ? fSearch.params : {};
    },
    $fTable() {
      return this.$refs.table;
    },
    $table() {
      return this.$refs.table.$refs.table;
    },
    $fDialog() {
      return this.$refs.dialog;
    },
    $dialog() {
      return this.$refs.dialog.$refs.dialog;
    },
    $fSearch() {
      return this.$refs.search;
    }
  },
  data() {
    return {
      crudConfig: this.$crudConfig || {},
      curRow: {},
      title: '',
      event: '',
      showTable: true,
      presetEvents: [
        {event: 'add', title: '新增'},
        {event: 'edit', title: '编辑'},
        {event: 'view', title: '查看'}
      ]
    };
  },
  methods: {
    /**
     * 切换表格列显隐
     * @param showIndexList
     * @param hideIndexList
     */
    handleColumnToggle({showIndexList, hideIndexList}) {
      this.showColumns(showIndexList);
      this.hideColumns(hideIndexList);
    },
    /**
     * 显示新增弹窗
     * @param title
     */
    showAdd(title = '新增') {
      this.handlePresetEvent(null, {event: 'add', title});
    },
    /**
     * 显示编辑弹窗
     * @param row
     * @param title
     */
    showEdit(row, title = '编辑') {
      this.handlePresetEvent(row, {event: 'edit', title});
    },
    /**
     * 显示查看弹窗
     * @param row
     * @param title
     */
    showView(row, title = '查看') {
      this.handlePresetEvent(row, {event: 'view', title});
    },
    /**
     * 提交搜索
     */
    submitSearch() {
      this.$fSearch.handleSearch();
    },
    /**
     * 重置搜索
     */
    resetSearch() {
      this.$fSearch.handleReset();
    },
    /**
     * 显示字段
     * @param columnIndexList {Array} 列索引
     * @param scopeName {'$table'|'$dialog'|'$search'} 作用域
     */
    showColumns(columnIndexList = [], scopeName) {
      this.toggleColumns(columnIndexList, scopeName, false);
    },
    /**
     * 隐藏字段
     * @param columnIndexList {Array} 列索引
     * @param scopeName {'$table'|'$dialog'|'$search'} 作用域
     */
    hideColumns(columnIndexList = [], scopeName) {
      this.toggleColumns(columnIndexList, scopeName, true);
    },
    /**
     * 切换字段显隐
     * @param columnIndexList {Array} 列索引
     * @param scopeName {'$table'|'$dialog'|'$search'} 作用域
     * @param flag
     */
    toggleColumns(columnIndexList = [], scopeName = '$table', flag) {
      let {columns} = this.config;
      columnIndexList.forEach(index => {
        let column = columns[index];
        if (!column) return;
        let scope = scopeName === '$table' ? column : column[scopeName];
        if (!scope) {
          column[scopeName] = {hide: flag};
        } else {
          scope.hide = flag;
        }
      });
    },
    /**
     * 处理自定义事件
     * @param row
     * @param event
     */
    handleCustomEvent({row, event}) {
      let e = this.presetEvents.find(v => v.event === event);
      if (e) {
        this.handlePresetEvent(row, e);
      } else {
        this.$emit(event, row);
      }
    },
    /**
     * 处理内置事件
     * @param row
     * @param e
     */
    handlePresetEvent(row, e) {
      let {event, title} = e;
      this.event = event;
      this.title = title;
      let {columns, beforeOpen} = this.config;
      let initValue = {};
      if (event === 'add') {
        columns.forEach(column => {
          let {$dialog = {}} = column;
          initValue[column.field] = $dialog.value;
        });
        this.curRow = initValue;
      } else {
        this.curRow = deepCopy(row);
      }
      let done = () => {
        this.$fDialog.visible = true;
        this.$nextTick(() => {
          this.$fDialog.resetForm();
        });
      };
      if (beforeOpen) {
        beforeOpen(this.curRow, done);
      } else {
        done();
      }
    },
    handleAdd() {
      this.handlePresetEvent(null, this.presetEvents[0]);
    }
  },
  render() {
    let {searchable = true, pageable = true, addable = true, showColumnToggle = false, addPermission} = this.config;
    let addBtn = this.config.$addBtn || this.crudConfig.$addBtn || {
      text: '新增',
      props: {type: 'primary', icon: 'Plus', plain: true},
      attrs: {}
    };
    let addData = {...addBtn.props, ...addBtn.attrs};
    return (
      <section class="f-crud">
        {searchable &&
          <f-search
            ref="search"
            hasResetSearchHandler={!!this.$attrs.onResetSearch}
            config={this.config}
            {...this.$attrs}
            v-slots={this.$slots}/>}
        {(addable || this.$slots.add) &&
          <el-form onSubmit={e => e.preventDefault()}>
            <el-form-item class="between">
              {addable &&
                <f-btn {...addData} permission={addPermission} onClick={this.handleAdd}>{addBtn.text}</f-btn>
              }
              {this.$slots.add && this.$slots.add()}
              {showColumnToggle &&
                <f-column-toggle
                  ref="column-toggle"
                  onColumnToggle={this.handleColumnToggle}
                  config={this.config}
                />
              }
            </el-form-item>
          </el-form>
        }
        {this.showTable &&
          <f-table
            ref="table"
            onCustomEvent={this.handleCustomEvent}
            loading={this.tableLoading}
            config={this.config}
            data={this.data}
            {...this.$attrs}
            v-slots={this.$slots}/>
        }
        {pageable &&
          <f-page
            ref="page"
            hasPageChangeHandler={!!this.$attrs.onPageChange}
            page={this.page}
            config={this.config}
            {...this.$attrs}
            v-slots={this.$slots}/>}
        <f-dialog
          ref="dialog"
          event={this.event}
          title={this.title}
          config={this.config}
          data={this.curRow}
          {...this.$attrs}
          v-slots={this.$slots}/>
      </section>
    );
  }
};
